{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import linearmodels\n",
    "import rqdatac as rq\n",
    "import tushare as ts\n",
    "from scipy import stats\n",
    "import statsmodels.api as sm\n",
    "from datetime import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [],
   "source": [
    "\n",
    "from typing import List\n",
    "\n",
    "\n",
    "class Beta_Anomaly(object):\n",
    "    \"\"\"\n",
    "    此代码要运行必须要米筐数据权限 米筐数据权限申请步骤：进入https://www.ricequant.com/welcome/edu网站\n",
    "    先在网站注册账号 然后在上方的地址下面进行数据权限申请（需要手持校卡、学生证、身份证或者录取通知书的照片）\n",
    "    教育邮箱在智慧广外处可找到（学号@gdufs.edu.cn）,\n",
    "    申请后一般会在两天内发成功通过的邮件到教育邮箱\n",
    "    在python端的登陆方式是先import rqdatac as rq, 然后rq.init('账号','密码')即可 ***：使用rqdata数据接口需要校园网才能调用数据\n",
    "\n",
    "    代码别非有偿，若已开通rqdata数据权限，希望能借账号给开发者研究一段时间（需要账号密码）\n",
    "\n",
    "    \"\"\"\n",
    "    def __init__(\n",
    "            self,\n",
    "            start_date:str,\n",
    "            end_date:str,\n",
    "            benchmark:str):\n",
    "        \"\"\"\n",
    "\n",
    "        author:Eden Franx 黄伟彬(交作业时记得删掉)\n",
    "        \n",
    "        start_date和end_date的日期必须是1号，避免生成月初月末日期时报错 such:'20210101'或者'2021-03-01'\n",
    "        :param start_date:\n",
    "        :param end_date:\n",
    "        :param benchmark: 基准指数可以是https://www.ricequant.com/doc/rqdata/python/indices-dictionary.html网站里面的指数代码\n",
    "        \"\"\"\n",
    "        try:\n",
    "            rq.init('')\n",
    "            rq.user.get_quota()\n",
    "        except:\n",
    "            print('radata未能成功初始化')\n",
    "            return\n",
    "\n",
    "        self.start_date = start_date\n",
    "        self.end_date = end_date\n",
    "        self.benchmark = benchmark\n",
    "        self.period_index_stocks = rq.index_components(\n",
    "                                                order_book_id=self.benchmark,\n",
    "                                                start_date=self.start_date,\n",
    "                                                end_date=self.end_date)\n",
    "        self.end_month_date = pd.date_range(start=self.start_date, end=self.end_date, freq='BM')         # 生成研究时段内工作日的月底日期\n",
    "        self.start_month_date =  pd.date_range(start=self.start_date, end=self.end_date, freq='BMS')[:-1]    # 生成研究时段内工作日的月初日期\n",
    "\n",
    "    def calculate_FFC_alpha(self, x, y):\n",
    "        \"\"\"\n",
    "        calculate each group alphas of the Fama-French and Carhart 4-factor model\n",
    "        :parameter x为dataframe或series，应该是month_group_return-rf数据\n",
    "        :parameter y为dataframe或series，可以是四因子或五因子\n",
    "        :return 该组的alpha因子值,即回归方程的截距项\n",
    "        \"\"\"\n",
    "        X = sm.add_constant(x)\n",
    "        est = sm.OLS(y,X).fit()\n",
    "\n",
    "        return est.params.const\n",
    "\n",
    "    def calculate_need_factor(self, code: List[str], start_date:str, end_date:str, data_frame):\n",
    "        \"\"\"使用时是获取某个月月末计算的，计算的时间跨度是1个月\n",
    "        :param data_frame:\n",
    "        :param start_date:月初日期\n",
    "        :param end_date:月末日期\n",
    "        :return 返回所有股票当月月底时因子数据（未进行分组）\n",
    "        \"\"\"\n",
    "        data = []\n",
    "        benchmark_price_series = rq.get_price(self.benchmark, start_date=start_date,\n",
    "                                              end_date=end_date).reset_index()\n",
    "        for stock in code:\n",
    "\n",
    "            stock_price_series = data_frame.query(f'(order_book_id==\"{stock}\")')[\n",
    "                ['close','volume','open','order_book_id','date']]\n",
    "\n",
    "            memory = {'stock': stock}\n",
    "            memory['beta'] = self._calculate_stock_beta(stock_price_series,benchmark_price_series)\n",
    "            month_market_return, month_return = self._calculate_return(stock_price_series,benchmark_price_series)\n",
    "            memory['month_return'] = month_return\n",
    "            memory['month_market_return'] = month_market_return\n",
    "\n",
    "            memory['market_value'] = data_frame['market_cap'].tolist()[-1]\n",
    "            memory['log_book_to_market'] = np.log(data_frame['book_to_market_ratio_ttm'].tolist()[-1])\n",
    "\n",
    "            memory['stock_illiquidity'] = self._calculate_stock_illiquidity(stock_price_series)\n",
    "            IVOL = self._calculate_idiosyncratic_volatility(\n",
    "                code, start_date,end_date, stock_price_series, benchmark_price_series)\n",
    "            memory['idiosyncratic_volatility'] = IVOL\n",
    "            memory['size'] = np.log(memory['market_value'])\n",
    "            memory['lottery_demand'] = self._calculate_lottery_demand(stock_price_series)\n",
    "\n",
    "            mom_start_date = (pd.to_datetime(end_date) - timedelta(days=365))\n",
    "            stock_return = rq.get_price(stock,start_date=mom_start_date,end_date=end_date,fields='close').close.tolist()\n",
    "            stock_log_return = np.log(stock_return[-1]/stock_return[0])\n",
    "            memory['momentum'] = stock_log_return\n",
    "            memory['skewness'] = stats.skew(stock_return)\n",
    "            #memory['coskewness'] = self._calculate_coskewness(stock, mom_start_date, end_date)\n",
    "            data.append(memory)\n",
    "\n",
    "        return pd.DataFrame(data)\n",
    "\n",
    "    def _calculate_coskewness(self, code:str, start_date, end_date, month_market_return, month_return):\n",
    "        rf = rq.get_yield_curve(start_date=start_date, end_date=end_date, tenor='1Y') # 获取国债一年期收益率当月时间序列\n",
    "        market_price = rq.get_price(self.benchmark, start_date, end_date, fields=['close','open'])\n",
    "        market_daily_return = (market_price.close - market_price.open)/market_price.open\n",
    "        stock_price = rq.get_price(code, start_date, end_date, fields=['close', 'open'])\n",
    "        stock_daily_return = (stock_price.close - stock_price.open)/stock_price.open\n",
    "\n",
    "        excess_return = (month_return.reset_index().rename(columns={'date': 'trading_date'}).set_index('trading_date')[0] - rf['1Y']).dropna()\n",
    "\n",
    "        x = pd.DataFrame(excess_return**2, columns=['mrf'])\n",
    "        y = (stock_daily_return.reset_index().rename(columns={'date': 'trading_date'}).set_index('trading_date')[0] - rf['1Y']).dropna()\n",
    "        X = sm.add_constant(np.array(x))\n",
    "        est = sm.OLS(np.array(y), X).fit()\n",
    "\n",
    "        return est.params['mrf']\n",
    "\n",
    "    def _calculate_lottery_demand(self, stock_price_series):\n",
    "        \"\"\"\n",
    "\n",
    "        :param code: 单个股票代码\n",
    "        :param start_date: 一般为月初\n",
    "        :param end_date: 一般为月末\n",
    "        :return: lottery因子\n",
    "        \"\"\"\n",
    "        stock_price = stock_price_series\n",
    "        stock_daily_return = np.array((stock_price.close - stock_price.open)/stock_price.open)\n",
    "        stock_daily_return = np.sort(stock_daily_return)\n",
    "\n",
    "        return np.average(stock_daily_return[-5:])\n",
    "\n",
    "    def _calculate_stock_illiquidity(self, stock_price_series) -> float:\n",
    "        \"\"\"\n",
    "        :param stock_price_series:单个股票的价格序列,要包含列名volume和close\n",
    "        \"\"\"\n",
    "        abs_return = np.array(abs(stock_price_series.close.diff())[1:])\n",
    "        volume = np.array(stock_price_series.volume[1:])\n",
    "        return (abs_return / volume).mean()\n",
    "\n",
    "    def _calculate_idiosyncratic_volatility(self, codes:List[str], start_date ,end_date,stock_price_series, benchmark_price_series):\n",
    "        \"\"\"\n",
    "        计算一个股票在时间段内的特质波动率\n",
    "        :param code:\n",
    "        :param start_date:\n",
    "        :param end_date:\n",
    "        :return: 返回一个股票在该月的IVOL因子\n",
    "        \"\"\"\n",
    "        stock_price_series = stock_price_series.rename(columns={'date': 'trading_date'}).set_index('trading_date')\n",
    "        benchmark_price_series = benchmark_price_series.rename(columns={'date': 'trading_date'}).set_index('trading_date')\n",
    "\n",
    "        rf = rq.get_yield_curve(start_date=start_date, end_date=end_date, tenor='1Y') # 获取国债一年期收益率当月时间序列\n",
    "\n",
    "        market_daily_return = (benchmark_price_series.close - benchmark_price_series.open\n",
    "                               )/benchmark_price_series.open\n",
    "        stock_daily_return = (stock_price_series.close - stock_price_series.open\n",
    "                              )/stock_price_series.open\n",
    "\n",
    "        x = pd.DataFrame(market_daily_return - rf['1Y']).dropna()\n",
    "\n",
    "        smb_hml = self._get_fama_french_factor(codes, end_date)\n",
    "        x['smb'] = smb_hml['smb']\n",
    "        x['hml'] = smb_hml['hml']\n",
    "\n",
    "        y = (stock_daily_return.reset_index().rename(columns={'date': 'trading_date'}).set_index('trading_date')[0] - rf['1Y']).dropna()\n",
    "\n",
    "        X = sm.add_constant(x)\n",
    "        est = sm.OLS(y, X).fit()\n",
    "\n",
    "        return np.std(est.resid) * len(stock_daily_return)**0.5\n",
    "\n",
    "    def _calculate_return(self, stock_price_series, benchmark_price_series) -> (float, float):\n",
    "        \"\"\"\n",
    "        the excess return of t month\n",
    "        \"\"\"\n",
    "        stock_close = stock_price_series.close.tolist()\n",
    "        benchmark_close = benchmark_price_series.close.tolist()\n",
    "\n",
    "        stock_return = (stock_close[-1] - stock_close[0])/stock_close[0]\n",
    "        benchmark_return = (benchmark_close[-1] - benchmark_close[0])/benchmark_close[0]\n",
    "\n",
    "        return benchmark_return, stock_return\n",
    "\n",
    "    def _calculate_stock_beta(self,stock_price_series:pd.DataFrame,\n",
    "                              benchmark_price_series:pd.DataFrame):\n",
    "\n",
    "        market_log_return = self.__get_log_return(benchmark_price_series)\n",
    "        stock_log_return = self.__get_log_return(stock_price_series)\n",
    "        df=pd.merge(market_log_return,stock_log_return,left_index=True,right_index=True)\n",
    "        x=df.iloc[:,0]\n",
    "        y=df.iloc[:,1]\n",
    "        beta,alpha,r_value,p_value,std_err=stats.linregress(x,y)\n",
    "        return beta\n",
    "\n",
    "    def __get_log_return(self, price_series) -> float:\n",
    "\n",
    "        code = price_series[['order_book_id']].iloc[0,0]\n",
    "        p1=np.array(price_series.close[1:])\n",
    "        p0=np.array(price_series.close[:-1])\n",
    "        logret = np.log(p1/p0)\n",
    "        rate=pd.DataFrame()\n",
    "        rate[code]=logret\n",
    "\n",
    "        return rate\n",
    "\n",
    "    def __get_mom_factor(self, code:List[str], date:str):\n",
    "        \"\"\"\n",
    "        :parameter code——某个月某个组的股票列表\n",
    "        :return 返回该组该月的MOM因子\n",
    "        \"\"\"\n",
    "        data = []\n",
    "        end_date = date\n",
    "        start_date = (pd.to_datetime(date) - timedelta(days=365))\n",
    "        for stock in code:\n",
    "            stock_return = rq.get_price(stock,start_date=start_date,end_date=end_date,fields='close').close.tolist()\n",
    "            stock_log_return = np.log(stock_return[-1]/stock_return[0])\n",
    "            data.append({'stock':stock, 'log_return':stock_log_return})\n",
    "\n",
    "        data = pd.DataFrame(data, index=code,columns=['log_return'])\n",
    "        pct_down, pct_up = data['log_return'].quantile([0.3, 0.7])\n",
    "        listBins = [data['log_return'].min()-1, pct_down, pct_up, data['log_return'].max()+1]\n",
    "        listLabels = ['L', 'M', 'H']\n",
    "\n",
    "        data['flag'] = pd.cut(data['log_return'], bins=listBins, labels=listLabels)\n",
    "        # 组合划分为2组\n",
    "        pct_L = data.query('flag==\"L\"')\n",
    "        pct_H = data.query('flag==\"H\"')\n",
    "        # 等权重计算动量因子\n",
    "        factor_momental = pct_H['log_return'].mean() - pct_L['log_return'].mean()\n",
    "        return factor_momental\n",
    "\n",
    "    def __get_ps_factor(self, code:List[str], date:str):\n",
    "        \"\"\"\n",
    "        :param code:\n",
    "        :param date:\n",
    "        :return:\n",
    "        \"\"\"\n",
    "\n",
    "        ps_factor = rq.get_factor(code, 'ps_ratio_ttm',date=date, expect_df=False)\n",
    "        return ps_factor.mean()\n",
    "\n",
    "    def _get_fama_french_factor(self, codes:List[str], date:str|datetime, add_factor:List[str] = []):\n",
    "        \"\"\"\n",
    "        该函数在 _calculate_FFC4_alpha函数里面运行\n",
    "        :parameter add_factor可选['ps']，默认为无，格式必须是列表\n",
    "        :parameter code为某月某个分组内的所有股票序列\n",
    "        :returns 返回该天的投资组合的经典因子数据，一般该天为月底\n",
    "        \"\"\"\n",
    "\n",
    "        factor_list = ['book_to_market_ratio_ttm','market_cap','ps_ratio_ttm']\n",
    "        frame = rq.get_factor(codes, factor_list, date=date)\n",
    "        prices = rq.get_price(codes,fields=['close','open'], start_date=date,end_date=date,frequency='1d')\n",
    "        frame = frame.join(prices).dropna()\n",
    "\n",
    "        frame['daily_return'] = (frame.close - frame.open) / frame.open\n",
    "        frame['SB'] = frame['market_cap'].map(lambda x: 'B' if x >= frame['market_cap'].median() else 'S')\n",
    "        # 求账面市值比：PB的倒数\n",
    "        frame['book_market'] = 1 / frame['book_to_market_ratio_ttm']\n",
    "        # 划分高、中、低账面市值比公司 3:4:3比例\n",
    "        border_down, border_up = frame['book_market'].quantile([0.3, 0.7])\n",
    "        frame['HML'] = frame['book_market'].map(lambda x: 'H' if x >= border_up else 'M')\n",
    "        frame['HML'] = frame.apply(lambda row: 'L' if row['book_market'] <= border_down else row['HML'], axis=1)\n",
    "\n",
    "        # 组合划分为6组\n",
    "        frame_SL = frame.query('(SB==\"S\") & (HML==\"L\")')\n",
    "        frame_SM = frame.query('(SB==\"S\") & (HML==\"M\")')\n",
    "        frame_SH = frame.query('(SB==\"S\") & (HML==\"H\")')\n",
    "        frame_BL = frame.query('(SB==\"B\") & (HML==\"L\")')\n",
    "        frame_BM = frame.query('(SB==\"B\") & (HML==\"M\")')\n",
    "        frame_BH = frame.query('(SB==\"B\") & (HML==\"H\")')\n",
    "\n",
    "        # 计算各组收益率\n",
    "        R_SL = frame_SL['daily_return'].sum()\n",
    "        R_SM = frame_SM['daily_return'].sum()\n",
    "        R_SH = frame_SH['daily_return'].sum()\n",
    "        R_BL = frame_BL['daily_return'].sum()\n",
    "        R_BM = frame_BM['daily_return'].sum()\n",
    "        R_BH = frame_BH['daily_return'].sum()\n",
    "\n",
    "        # 计算SMB, HML并返回\n",
    "        smb = (R_SL + R_SM + R_SH - R_BL - R_BM - R_BH) / 3\n",
    "        hml = (R_SH + R_BH - R_SL - R_BL) / 2\n",
    "\n",
    "        # 计算超额回报率\n",
    "        feedback = {'smb':smb, 'hml':hml}\n",
    "\n",
    "        if 'mom' in add_factor:\n",
    "            feedback['mom'] = self.__get_mom_factor(codes, date)\n",
    "        if 'ps' in add_factor:\n",
    "            feedback['ps'] = np.mean(frame['ps_ratio_ttm'].tolist())#self.__get_ps_factor(codes, date)\n",
    "\n",
    "        return feedback\n",
    "\n",
    "    def get_all_factor(self):\n",
    "        \"\"\"\n",
    "\n",
    "        \"\"\"\n",
    "\n",
    "        self.regress_data = pd.DataFrame()\n",
    "        for i in range(len(self.start_month_date)):\n",
    "            index_stocks: list = rq.index_components(order_book_id=self.benchmark,\n",
    "                                               date=self.end_month_date[i])\n",
    "            all_factor = rq.get_price(index_stocks,start_date=self.start_month_date[i],\n",
    "                                                   end_date = self.end_month_date[i],\n",
    "                                      fields=['close','open','volume'])\n",
    "            financial_factor = rq.get_factor(index_stocks,\n",
    "                                             start_date=self.start_month_date[i],\n",
    "                                             end_date = self.end_month_date[i],\n",
    "                                             factor=['market_cap',\n",
    "                                                     'ps_ratio_ttm',\n",
    "                                                     'book_to_market_ratio_ttm'])\n",
    "            all_factor = all_factor.join(financial_factor).reset_index().dropna()\n",
    "            #print(all_factor.query('(order_book_id==\"601669.XSHG\")'))\n",
    "            beta_frame = self.calculate_need_factor(index_stocks,\n",
    "                                                   start_date=self.start_month_date[i],\n",
    "                                                   end_date = self.end_month_date[i],\n",
    "                                                    data_frame=all_factor)\n",
    "            beta_frame['date'] = self.end_month_date[i]\n",
    "\n",
    "            self.regress_data = self.regress_data.append(beta_frame)\n",
    "            print(f\"{self.end_month_date[i]}处理完毕\")\n",
    "\n",
    "    def separate_groups_by_x(self, order:str):\n",
    "        self.sort_result = []\n",
    "        for i in range(len(self.start_month_date)):\n",
    "            frame = self.regress_data[self.regress_data.date == self.end_month_date[i]].sort_values(order)\n",
    "\n",
    "            divide_group = np.array_split(frame, 10) # 分十组\n",
    "            rf = float(rq.get_yield_curve(start_date=self.end_month_date[i],end_date=self.end_month_date[i],tenor='1Y').values) # 获取当日国债一年期收益率\n",
    "\n",
    "            for tuples in enumerate(divide_group):\n",
    "                group_data = {}\n",
    "                each_group_frame = tuples[1]\n",
    "                group_number = tuples[0]\n",
    "                each_group_stocks = each_group_frame['stock'].tolist()\n",
    "\n",
    "                group_data['date'] = self.end_month_date[i]\n",
    "                group_data['group'] = f'G{group_number + 1}'\n",
    "\n",
    "                group_data['month_group_return'] = np.average(each_group_frame['month_return'],weights=each_group_frame['market_value'])\n",
    "                group_data['month_group_return-rf'] = group_data['month_group_return'] - rf\n",
    "                group_data['month_market_return-rf'] = each_group_frame['month_market_return'].mean() - rf\n",
    "                group_data.update(self._get_fama_french_factor(codes=each_group_stocks, date=self.end_month_date[i], add_factor=['ps','mom']))\n",
    "\n",
    "                group_data['group_beta']  = each_group_frame.beta.mean()\n",
    "                group_data['MKTCAP'] = each_group_frame.market_value.mean()\n",
    "                group_data['MAX'] = each_group_frame.lottery_demand.mean()\n",
    "                group_data['BM'] = each_group_frame.log_book_to_market.mean()\n",
    "                group_data['MOM'] = each_group_frame.momentum.mean()\n",
    "                group_data['ILLIQ'] = each_group_frame.stock_illiquidity.mean()\n",
    "                group_data['IVOL'] = each_group_frame.idiosyncratic_volatility.mean()\n",
    "                #group_data['COSKEW'] = each_group_frame.coskewness.mean()\n",
    "                group_data['TSKEW'] = each_group_frame.skewness.mean()\n",
    "\n",
    "                self.sort_result.append(group_data)\n",
    "\n",
    "        self.sort_result = pd.DataFrame(self.sort_result)\n",
    "\n",
    "    def get_Table(self):\n",
    "        data = self.sort_result.groupby('group').mean()\n",
    "        Tabel_need = data[['group_beta','month_group_return-rf','MAX',\n",
    "                           'MKTCAP','BM','MOM','ILLIQ','IVOL','TSKEW']]\n",
    "\n",
    "        G_number = data.index\n",
    "        alpha_list = []\n",
    "        for group in G_number:\n",
    "            alpha = {}\n",
    "            soga = self.sort_result.query(f'(group==\"{group}\")')\n",
    "            x1, y = soga[['month_market_return-rf','smb','hml','mom']], soga['month_group_return-rf']\n",
    "            x2 = soga[['month_market_return-rf','smb','hml','mom','ps']]\n",
    "\n",
    "            alpha['FFC4-@'] = self.calculate_FFC_alpha(x1, y)\n",
    "            alpha['FFC4+PS-@'] = self.calculate_FFC_alpha(x2, y)\n",
    "            alpha_list.append(alpha)\n",
    "        alpha_frame = pd.DataFrame(alpha_list, index=G_number)\n",
    "        return Tabel_need.join(alpha_frame)\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2021-01-29 00:00:00处理完毕\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n",
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n",
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2021-02-26 00:00:00处理完毕\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2021-03-31 00:00:00处理完毕\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2021-04-30 00:00:00处理完毕\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2021-05-31 00:00:00处理完毕\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n",
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n",
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2021-06-30 00:00:00处理完毕\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n",
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2021-07-30 00:00:00处理完毕\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2021-08-31 00:00:00处理完毕\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2021-09-30 00:00:00处理完毕\n",
      "2021-10-29 00:00:00处理完毕\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n",
      "C:\\Users\\Eden\\AppData\\Local\\Temp\\ipykernel_60240\\4040613760.py:126: RuntimeWarning: invalid value encountered in true_divide\n",
      "  return (abs_return / volume).mean()\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2021-11-30 00:00:00处理完毕\n"
     ]
    }
   ],
   "source": [
    "\n",
    "a = Beta_Anomaly('20210101','20220101','000300.XSHG')\n",
    "a.get_all_factor()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "\"Table 2\"\n",
    "a.separate_groups_by_x('lottery_demand')\n",
    "round(a.get_Table())"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": true
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "\"\"\"Table 1\"\"\"\n",
    "a.separate_groups_by_x('beta')\n",
    "round(a.get_Table().sort_values('group_beta'), 3)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": true
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "\"Table 4\"\n",
    "def T_profile(x):\n",
    "    return (x.mean() - 0)/(np.std(x)/(len(x)-1)**0.5)\n",
    "first_variable = ['beta','size','log_book_to_market', 'momentum']\n",
    "second_variable = first_variable + ['skewness','idiosyncratic_volatility']\n",
    "\n",
    "third_variable = first_variable + ['lottery_demand']\n",
    "fourth_variable = third_variable + ['skewness','idiosyncratic_volatility']\n",
    "variables = [first_variable,second_variable,third_variable,fourth_variable]\n",
    "\n",
    "for variable in variables:\n",
    "    regress_result = []\n",
    "    for date in set(a.regress_data['date']):\n",
    "        ddd = {}\n",
    "        end_month_data = a.regress_data.query(f\"(date=='{date}')\").dropna()\n",
    "\n",
    "        x = end_month_data[variable]\n",
    "        y = end_month_data['month_return']\n",
    "\n",
    "        X = sm.add_constant(x)\n",
    "        est = sm.OLS(y,X).fit()\n",
    "        regress_result.append(est.params.to_dict())\n",
    "\n",
    "    c = pd.DataFrame(regress_result)\n",
    "    b = c.apply(lambda x: T_profile(x), axis=0)\n",
    "    d = pd.DataFrame(b,columns=['t'])\n",
    "    d['mean'] = round(c.mean(),3)\n",
    "    print(d)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": true
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "ddd = a.sort_result.query('(group==\"G7\")')\n",
    "XX = ddd[['group_beta','MAX','BM','MOM','IVOL','TSKEW','MKTCAP','ILLIQ']]\n",
    "yy = ddd['month_group_return']\n",
    "\n",
    "XXX = sm.add_constant(XX)\n",
    "est = sm.OLS(yy, XXX).fit()\n",
    "print(est.summary())"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": true
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [
    {
     "data": {
      "text/plain": "        0\n0  2.2341\n1  3.0000\n2  4.0000\n3  5.0000\n4  6.0000",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>0</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>2.2341</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>3.0000</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>4.0000</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>5.0000</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>6.0000</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}